package org.sergiy.forecast;

import java.net.URL;
import java.util.List;
import java.io.File;
import java.io.InputStream;

import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import au.gov.bom.weather.AreaType;
import au.gov.bom.weather.BomWeatherService;
import au.gov.bom.weather.DefaultBomWeatherService;
import au.gov.bom.weather.ForecastPeriodType;
import au.gov.bom.weather.ForecastType;
import au.gov.bom.weather.ProductType;
import au.gov.bom.weather.TextElementType;

/**
 * Test of Our weather service facade
 *   
 * @author Sergiy Litsenko
 *
 */
@Test
public class WeatherServiceTestCase extends ForecastCoreTestCase {
	
	@BeforeClass
	@Override
	protected void init() throws Exception {
		super.init();
	}

	@AfterClass
	@Override
	protected void destroy() throws Exception {
		super.destroy();
	}

	@BeforeMethod
	@Override
	protected void setUp() throws Exception {
		super.setUp();
	}

	@AfterMethod
	@Override
	protected void tearDown() throws Exception {
		super.tearDown();
	}
	
	/**
	 * Get instance of WeatherService
	 * @return instance of WeatherService
	 */
	protected WeatherService getWeatherService () {
		return new DefaultWeatherService();
	}

	/**
	 * Test forecast data provided
	 * @param forecast
	 * @throws Exception
	 */
	protected void testForecast (Forecast forecast) throws Exception {
		// test 
		Assert.assertNotNull (forecast, "Weather Service must return todays forecast");
		Assert.assertNotNull (forecast.getLocationName(), "Location shall be specified");
		Assert.assertNotNull (forecast.getStartDate(), "Start date shall be specified");
		Assert.assertNotNull (forecast.getEndDate(), "End date shall be specified");
		// some data not always provided for all forecasts (specifically for todays forecast)
		//Assert.assertNotNull (forecast.getAirTemperatureMinimum(), "Min temperature shall be specified");
		//Assert.assertNotNull (forecast.getAirTemperatureMaximum(), "Max temperature shall be specified");
		//Assert.assertNotNull (forecast.getForecastBriefDescription(), "Brief description shall be specified");
		//Assert.assertNotNull (forecast.getIconCode(), "Icon codee shall be specified");
	}
	
	/**
	 * Valid values for testing Override File Name Behaviour
	 */
	@DataProvider(name = "validLocationsForWeatherService")
	public Object[][] createValidLocationsForBomService() throws Exception {
		return new Object[][] {
				{"Sydney"},
				{"Bondi"},
				{"Parramatta"},
				{"Canberra"}
		};
	}
	
	
	@Test (dataProvider = "validLocationsForWeatherService")
	public void testWeatherServiceTodayForecast(String location) throws Exception {
		// start marker
		logStartTestMarker ("testWeatherServiceTodayForecast");		
		
		// debug
		if (log.isDebugEnabled()) {
			log.debug(String.format("Testing the today's forecast for location: %1$s", location));
		}
		
		// Get instance of BomWeatherService
		WeatherService service = getWeatherService ();
		// test
		Assert.assertNotNull (service, "Weather Service must exists");
		
		// get product
		Forecast forecast = service.getForecast(location);
		
		// debug
		if (log.isDebugEnabled()) {
			log.debug(String.format("today's forecast for location: %1$s - %2$s", location, forecast));
		}
		
		// Test forecast data provided
		testForecast (forecast);
	}

	@Test (dataProvider = "validLocationsForWeatherService")
	public void testWeatherServiceWeeklyForecast(String location) throws Exception {
		// start marker
		logStartTestMarker ("testWeatherServiceWeeklyForecast");		
		
		// debug
		if (log.isDebugEnabled()) {
			log.debug(String.format("Testing the weekly forecast for location: %1$s", location));
		}
		
		// Get instance of BomWeatherService
		WeatherService service = getWeatherService ();
		// test
		Assert.assertNotNull (service, "Weather Service must exists");
		
		// get weekly forecast
		List<Forecast> weeklyForecast = service.getWeeklyForecast(location);
		
		// debug
		if (log.isDebugEnabled()) {
			log.debug(String.format("Weekly forecast for location: %1$s - %2$s", location, weeklyForecast));
		}
		
		// test
		Assert.assertNotNull (weeklyForecast, "Weather Service must return weekly forecast");
		Assert.assertFalse (weeklyForecast.isEmpty(), "Weather Service must return not empty weekly forecast"); 
		
		// Test forecast data provided for entire week
		for (Forecast forecast : weeklyForecast) {
			testForecast (forecast);
		}
	}
}
